Author(s): Zongcheng Li
Reviewer(s): Ying Ge, Yasi Zhang
Date: 2025-11-21

1 Academic Citation

If you use this code in your work or research, we kindly request that you cite our publication:

Xiaofan Lu, et al. (2025). FigureYa: A Standardized Visualization Framework for Enhancing Biomedical Data Interpretation and Research Efficiency. iMetaMed. https://doi.org/10.1002/imm3.70005

2 需求描述 Requirement description

画出这种连线图。

Draw this connection diagram.

From https://molecular-cancer.biomedcentral.com/articles/10.1186/s12943-021-01322-w, from the same article as FigureYa260CNV.

Fig. 5 Transcriptional and post-transcriptional characteristics associated with the WM_Score. a Differences in miRNA-targeted signaling pathways in the TCGA-COAD/READ cohort between the WM_Score-high and -low groups. The red line represents a low expression of miRNA in the high WM_Score group, and the blue line represents a high expression of miRNA in the low WM_Score group. Red dots correspond to miRNA-targeted genes highly expressed in the high WM_Score group, and blue dots correspond to miRNA-targeted genes highly expressed in the low WM_Score group. The circle represents a signaling pathway enriched with targeted genes.

类似的图:

A similar image:

出自:https://doi.org/10.1038/s42255-019-0045-8,跟FigureYa174squareCross、FigureYa199crosslink、FigureYa256panelLink出自同一篇文章。这篇文章以连线著称,总是被模仿,不知道会不会被超越。

From https://doi.org/10.1038/s42255-019-0045-8, from the same article as FigureYa174squareCross, FigureYa199crosslink, and FigureYa256panelLink. This paper is renowned for its connection designs—constantly imitated, yet to be surpassed.

Fig. 3 | overview of the propensity score algorithm and the hypoxia-associated molecular patterns across cancer types. c, Association between mRNA expression levels of hypoxia-associated genes and drug sensitivity across 1,074 cancer cell lines by Spearman’s rank correlation. The dark green dots along the x axis indicate hypoxia-related genes; the orange dots denote drugs that are clustered by different signalling pathways. The size of the orange dot indicates the number of genes correlated with drug sensitivity (|rs| > 0.3, FDR < 0.05); the bar plot shows the number of drugs correlated with the genes. The pink and cyan lines indicate positive and negative correlation, respectively. JNK, Jun N-terminal kinase.

3 应用场景 Application scenarios

展示miRNA-靶基因(或基因-药物等)的关系,连线和节点的颜色代表节点类型(例如例文的high和low WM_Score)。同一通路的基因画在同一圆圈里,并标注通路名。

为了画这个图,完善了crosslink包,该R包会继续添加更多有趣的连线功能,感兴趣可前往https://github.com/zzwch/crosslink查看最新版本及功能,在github上还能提交issue跟作者直接交流。

This figure displays miRNA-target gene (or gene-drug, etc.) relationships, where the colors of connecting lines and nodes represent node types (e.g., high vs. low WM_Score as shown in the example). Genes from the same pathway are grouped within circular clusters labeled with pathway names.

To create this visualization, we enhanced the crosslink R package, which will continue to incorporate more innovative connection features. Those interested can visit https://github.com/zzwch/crosslink to explore the latest version and functionalities. GitHub also allows users to submit issues for direct communication with the author.

4 环境设置 Environment Setup

source("install_dependencies.R")
## Starting R package installation...
## ===========================================
## 
## Installing CRAN packages...
## Package already installed: ggplot2 
## Package already installed: magrittr 
## Package already installed: tidyverse 
## Package already installed: rlang 
## Package already installed: patchwork 
## 
## ===========================================
## Package installation completed!
## You can now run your R scripts in this directory.
source("crosslink.R") # From R package crosslink
source("layout.R") # From R package crosslink
source("transfromation.R") # From R package crosslink
source("utils.R") # From R package crosslink

library(magrittr)    # 管道操作符 Pipe operations
library(tidyverse)   # 数据整理与可视化 Data wrangling & visualization
library(ggplot2)     # 绘图 Plotting
library(rlang)       # 编程辅助 Programming tools
library(patchwork)   # 拼图 Plot composition

# 显示英文报错信息
# Show English error messages
Sys.setenv(LANGUAGE = "en") 

# 禁止chr转成factor
# Prevent character-to-factor conversion
options(stringsAsFactors = FALSE) 

5 输入文件 Input Files

easy_input_links.csv,连线表示source(miRNA)和target(靶基因)的关系。连线的颜色表示source的类型source_type(high WM_Score和low WM_Score)。

easy_input_nodes.csv,key(包括source和target)所在的path(通路)信息。

  • 节点的颜色表示target的类型type(high WM_Score和low WM_Score)。
  • source(miRNA)的path列写为source,source的type列是source的type,因此跟easy_input_links.csv的source_type列一致,signif列的内容会标在图中source的名字下面。
  • 如果想要例文2那样的效果,用target节点的大小表示number of genes correlated to drug sensitivity,就加一列size,用于控制targe节点的大小,记得把文档中# size = size前面的#删掉。

easy_input_links.csv represents the relationship between the source (miRNA) and the target (target gene), where the color of the line indicates the type of the source (source_type: high WM_Score and low WM_Score).

easy_input_nodes.csv contains the pathway information (path) for the keys (including both source and target).

  • The color of the nodes represents the type of the target (type: high WM_Score and low WM_Score).
  • For the source (miRNA), the path column should be labeled as “source,” and the type column corresponds to the source’s type, which should match the source_type column in easy_input_links.csv. The content of the signif column will be displayed below the name of the source in the diagram.
  • If you want an effect similar to Example 2, where the size of the target nodes represents the “number of genes correlated to drug sensitivity,” add a column named “size” to control the size of the target nodes. Remember to remove # in # size = size in the document.
links <- read.csv("easy_input_links.csv")
nodes <- read.csv("easy_input_nodes.csv")

# 获取所有通路的名字
# Get all pathway names
paths <- unique(nodes[nodes$path != "source", ]$path) 

# 把"source"排在前面
# Place "source" first  
nodes$path <- factor(nodes$path, levels = c("source", paths)) 

# 连线的颜色
# Line colors 
src_up_col <- "red"
src_dn_col <- "blue"

# target节点的颜色
# Target node colors 
tar_up_col <- "red"
tar_dn_col <- "blue"

6 开始画图 Plotting

6.1 快速预览 Take a glance of the data

重要提示!节点和边数据中不能包含列名 ‘node’、‘cross’、‘node.type’、‘x’、‘y’、‘degree’!

IMPORTANT! The colnames of ‘node’, ‘cross’, ‘node.type’, ‘x’, ‘y’, ‘degree’ MUST NOT BE included in nodes and edges!

# 使用crosslink函数创建网络布局对象
# Create network layout object using crosslink function
toy <- crosslink(
  nodes = nodes, 
  edges = links,
  cross.by = "path", 
  xrange = c(0, 10),
  yrange = c(-5, 5),
  spaces = "partition")

# 绘制网络布局图
# Plot the network layout
cl_plot(toy)

6.2 按通路将靶点转换为圆形分布 Transform the targets into circle by pathways

# 自定义函数
# Custom function
toCircle <- function(x, y, rx = 1, ry =1, intensity = 2){
  mapTo2pi <- function(x) {scales::rescale(c(0, x), to = c(0, 2*pi))[-1]}
  data.frame(x, y) %>%
    mutate(group = paste0("group", x)) %>%
    mutate(yy = scales::rescale(-x, to = range(y))) %>%
    mutate(xx = mean(x) + intensity * sin(yy %>% mapTo2pi),) %>%
    group_by(group) %>%
    mutate(tri = rank(y, ties.method = "first") %>% mapTo2pi)  %>%
    ungroup() %$%
    data.frame(
      x = xx + rx*sin(tri),
      y = yy + ry*cos(tri))
}

# 应用圆形变换函数到网络布局对象
# Apply circular transformation to network layout object
toy_circle <- toy %>% tf_fun(
  crosses = paths, 
  along = "xy",
  fun = toCircle,
  rx = 0.2, ry = 0.2)

# 绘制变换后的网络图(不显示标签)
# Plot transformed network (without labels)
toy_circle %>% cl_plot(label = NA)

6.3 后处理 Post-processing

## 对圆形布局进行几何变换
## Geometric transformations for circular layout
toy_final <- toy_circle %>% 
  tf_rotate(angle = -90) %>% 
  tf_flip(axis = "x", crosses = paths) %>%
  tf_shift(y = 8, crosses = paths, relative = F) %>%
  set_header()

## 可视化后处理结果
## Visualize post-processing results
toy_final %>% cl_plot(label = NA) %>% cl_void()

6.4 微调 Fine tuning

# 显示可用图形属性
# Display available graphic attributes
show_aes(toy_final)
## Available meta.data names are showing below.
## Cross: node, node.type, x, y, cross, key, type, path, signif, degree 
## Link: src, tar, source_type, src.cross, tar.cross, source, target, src.degree, tar.degree, x, y, xend, yend 
## Header: node, node.type, x, y, cross, header
ggplot() +
  # 每个模块相对独立,可根据需要调整不同图层的叠加顺序
  # Each module is relatively independent, you can adjust the layer stacking order as needed
  
  # 路径的黑色圆圈(绘制在最底层,部分会被靶点覆盖)
  # Black circles for pathways (drawn at the bottom layer, partially covered by target points)
  ggforce::geom_circle(
    mapping = aes(x0 = x0, y0 = y0, r = r),
    data = get_cross(toy_final) %>% filter(cross != "source") %>% 
      group_by(path) %>%
      transmute(
        x0 = mean(x),
        y0 = mean(y),
        r = 0.2
      ) %>% unique(),
    show.legend = F
  ) +
  
  # 连线(miRNA-靶基因关系)
  # Connection lines (miRNA-target relationships)
  geom_segment(
    mapping = aes(x, y, xend = xend, yend = yend, color = source_type),
    data = get_link(toy_final),
    alpha = 0.3 
  ) + 
  
  # 靶点节点
  # Target nodes
  geom_point(
    mapping = aes(x, y, 
                  # size = size, 
                  color = type),
    data = get_cross(toy_final) %>% filter(cross != "source")
  ) +
  
  # 添加文字:靶点所属通路名称
  # Add text: Pathway names for targets
  ggrepel::geom_text_repel(
    mapping = aes(x, y, label = header), nudge_y = 0.3, 
    data = get_header(toy_final) %>% filter(cross != "source"),
    segment.color = NA
  ) +
  
  # 添加文字:miRNA源节点名称
  # Add text: miRNA source node names
  geom_text(
    mapping = aes(x, y, label = key), angle = 90, hjust = 1, nudge_y = -0.1,
    data = get_cross(toy_final) %>% filter(cross == "source")
  ) +
  
  # 添加文字:每个通路的靶点数量
  # Add text: Number of targets per pathway
  geom_text(
    mapping = aes(x, y, label = num),
    data = get_cross(toy_final) %>% filter(cross != "source") %>% 
      group_by(path) %>%
      transmute(
        x = mean(x),
        y = mean(y),
        num = n()
      ) %>% unique()
  ) +
 
  # 颜色配置
  # Color settings
  scale_color_manual(values = c(
      src_up = src_up_col, src_dn = src_dn_col, 
      tar_up = tar_up_col, tar_dn = tar_dn_col)) + 
  labs(x = NULL, y = "Target_Pathway") +
  scale_y_continuous(expand = expansion(mult = c(0.25,0.1))) -> p

p

如果想要像例文2那样给source也画上点,就运行下面这段

If you want to plot points for the source nodes as in Example 2, run the following code

# 画source节点
# Plot source nodes
p <- p + geom_point(
  mapping = aes(x, y),
  data = get_cross(toy_final) %>% filter(cross == "source")
  )

6.5 添加注释图 Add annotation plots

把source的’signif’标注在source名字的下方

Place the ‘signif’ annotation below the source names

# 创建带注释的circLink图
# Create circLink plot with annotations
cl_plot2(
  p %>% cl_void(th = theme(
    axis.title = element_text())),
  object = toy_final, 
  annotation = cl_annotation(
    bottom = ggplot() +
      geom_text(
        mapping = aes(seq_along(key), 0, label = signif), 
        data = nodes %>% filter(path == "source")
      ) + theme_void() 
    ,
    bottom.by = "source", bottom.height = 0.05
  )
)

# 保存图形为PDF文件
# Save plot as PDF file
ggsave("circLink.pdf", width = 10, height = 5)

7 附:示例数据生成过程 Appendix: Example Data Generation Process

# 生成节点名称
# Generate node names
sources <- paste0("source", 1:20 %>% format)
targets <- paste0("target", 1:500 %>% format)
paths <- paste0("path", 1:15 %>% format)

# 创建节点数据框
# Create node dataframe
nodes <- data.frame(
  key = c(sources, targets),
  type = c(rep("src_up", length(sources)/2),
           rep("src_dn", length(sources)/2),
           sample(c("tar_up", "tar_dn"), length(targets), replace = T)),
  path = c(rep("source", length(sources)), 
           rep(paths, times = c(
             40, 50, 30, 30, 50, 50, 20, 30, 30, 40, 20, 30, 30, 20, 30
           ))) %>% factor(
             levels = c("source", paths)
           ),
  signif = c(sample(c("*", "**", "***", "ns"), length(sources), replace = T),
             rep(NA, length(targets)))
)

# 生成连接关系数据
# Generate link relationships
link_n <- 500
set.seed(666)
links <- data.frame(
  src = sample(sources, link_n, replace = T),
  tar = sample(targets, link_n, replace = T)) %>% 
  unique() %>%
  mutate(source_type = nodes$type[match(src, nodes$key)])

# 保存示例数据文件
# Save example data files
write.csv(links, "easy_input_links.csv", row.names = F, quote = F)
write.csv(nodes, "easy_input_nodes.csv", row.names = F, quote = F)

8 Session Info

sessionInfo()
## R version 4.5.1 (2025-06-13)
## Platform: x86_64-apple-darwin20
## Running under: macOS Monterey 12.7.6
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: Asia/Shanghai
## tzcode source: internal
## 
## attached base packages:
## [1] grid      stats4    stats     graphics  grDevices utils     datasets 
## [8] methods   base     
## 
## other attached packages:
##  [1] crosslink_0.1.0             patchwork_1.3.2            
##  [3] rlang_1.1.6                 lubridate_1.9.4            
##  [5] forcats_1.0.1               stringr_1.5.2              
##  [7] purrr_1.2.0                 readr_2.1.5                
##  [9] tibble_3.3.0                tidyverse_2.0.0            
## [11] ggstatsplot_0.13.3          tidyr_1.3.1                
## [13] dplyr_1.1.4                 data.table_1.17.8          
## [15] shape_1.4.6.1               future_1.67.0              
## [17] survival_3.8-3              TCGAbiolinks_2.36.0        
## [19] SeuratData_0.2.2.9002       RColorBrewer_1.1-3         
## [21] ggrepel_0.9.6               ggraph_2.2.2               
## [23] Seurat_5.3.1                SeuratObject_5.2.0         
## [25] sp_2.2-0                    SingleCellExperiment_1.30.1
## [27] SummarizedExperiment_1.38.1 GenomicRanges_1.60.0       
## [29] GenomeInfoDb_1.44.3         MatrixGenerics_1.20.0      
## [31] matrixStats_1.5.0           plyr_1.8.9                 
## [33] corrplot_0.95               magrittr_2.0.4             
## [35] igraph_2.2.0                reshape2_1.4.4             
## [37] ggplot2_4.0.1               clusterProfiler_4.16.0     
## [39] org.Hs.eg.db_3.21.0         AnnotationDbi_1.70.0       
## [41] IRanges_2.42.0              S4Vectors_0.46.0           
## [43] Biobase_2.68.0              BiocGenerics_0.54.1        
## [45] generics_0.1.4             
## 
## loaded via a namespace (and not attached):
##   [1] R.methodsS3_1.8.2           dichromat_2.0-0.1          
##   [3] progress_1.2.3              goftest_1.2-3              
##   [5] Biostrings_2.76.0           vctrs_0.6.5                
##   [7] ggtangle_0.0.7              spatstat.random_3.4-2      
##   [9] effectsize_1.0.1            digest_0.6.39              
##  [11] png_0.1-8                   bayestestR_0.17.0          
##  [13] correlation_0.8.8           deldir_2.0-4               
##  [15] parallelly_1.45.1           MASS_7.3-65                
##  [17] httpuv_1.6.16               qvalue_2.40.0              
##  [19] withr_3.0.2                 xfun_0.54                  
##  [21] ggfun_0.2.0                 ellipsis_0.3.2             
##  [23] memoise_2.0.1               MatrixModels_0.5-4         
##  [25] gson_0.1.0                  parameters_0.28.2          
##  [27] systemfonts_1.3.1           ragg_1.5.0                 
##  [29] tidytree_0.4.6              zoo_1.8-14                 
##  [31] pbapply_1.7-4               R.oo_1.27.1                
##  [33] prettyunits_1.2.0           datawizard_1.3.0           
##  [35] rematch2_2.1.2              KEGGREST_1.48.1            
##  [37] promises_1.3.3              httr_1.4.7                 
##  [39] downloader_0.4.1            globals_0.18.0             
##  [41] fitdistrplus_1.2-4          rstudioapi_0.17.1          
##  [43] ps_1.9.1                    UCSC.utils_1.4.0           
##  [45] miniUI_0.1.2                DOSE_4.2.0                 
##  [47] processx_3.8.6              curl_7.0.0                 
##  [49] polyclip_1.10-7             GenomeInfoDbData_1.2.14    
##  [51] SparseArray_1.8.1           xtable_1.8-4               
##  [53] desc_1.4.3                  evaluate_1.0.5             
##  [55] S4Arrays_1.8.1              BiocFileCache_2.16.2       
##  [57] hms_1.1.4                   irlba_2.3.5.1              
##  [59] colorspace_2.1-2            filelock_1.0.3             
##  [61] ROCR_1.0-11                 reticulate_1.43.0          
##  [63] spatstat.data_3.1-9         lmtest_0.9-40              
##  [65] later_1.4.4                 viridis_0.6.5              
##  [67] ggtree_3.16.3               lattice_0.22-7             
##  [69] spatstat.geom_3.6-0         future.apply_1.20.0        
##  [71] scattermore_1.2             XML_3.99-0.19              
##  [73] cowplot_1.2.0               RcppAnnoy_0.0.22           
##  [75] pillar_1.11.1               nlme_3.1-168               
##  [77] compiler_4.5.1              RSpectra_0.16-2            
##  [79] stringi_1.8.7               tensor_1.5.1               
##  [81] devtools_2.4.6              crayon_1.5.3               
##  [83] abind_1.4-8                 gridGraphics_0.5-1         
##  [85] graphlayouts_1.2.2          bit_4.6.0                  
##  [87] chromote_0.5.1              fastmatch_1.1-6            
##  [89] codetools_0.2-20            textshaping_1.0.4          
##  [91] bslib_0.9.0                 paletteer_1.6.0            
##  [93] plotly_4.11.0               mime_0.13                  
##  [95] splines_4.5.1               Rcpp_1.1.0                 
##  [97] fastDummies_1.7.5           dbplyr_2.5.1               
##  [99] TCGAbiolinksGUI.data_1.28.0 knitr_1.50                 
## [101] blob_1.2.4                  fs_1.6.6                   
## [103] listenv_0.9.1               pkgbuild_1.4.8             
## [105] ggplotify_0.1.3             Matrix_1.7-3               
## [107] callr_3.7.6                 statmod_1.5.1              
## [109] tzdb_0.5.0                  tweenr_2.0.3               
## [111] pkgconfig_2.0.3             tools_4.5.1                
## [113] cachem_1.1.0                RSQLite_2.4.3              
## [115] viridisLite_0.4.2           rvest_1.0.5                
## [117] DBI_1.2.3                   fastmap_1.2.0              
## [119] rmarkdown_2.30              scales_1.4.0               
## [121] usethis_3.2.1               ica_1.0-3                  
## [123] sass_0.4.10                 coda_0.19-4.1              
## [125] insight_1.4.2               dotCall64_1.2              
## [127] RANN_2.6.2                  farver_2.1.2               
## [129] mgcv_1.9-3                  tidygraph_1.3.1            
## [131] yaml_2.3.10                 cli_3.6.5                  
## [133] BayesFactor_0.9.12-4.7      lifecycle_1.0.4            
## [135] uwot_0.2.3                  mvtnorm_1.3-3              
## [137] sessioninfo_1.2.3           BiocParallel_1.42.2        
## [139] timechange_0.3.0            gtable_0.3.6               
## [141] ggridges_0.5.7              progressr_0.17.0           
## [143] parallel_4.5.1              ape_5.8-1                  
## [145] limma_3.64.3                jsonlite_2.0.0             
## [147] RcppHNSW_0.6.0              bit64_4.6.0-1              
## [149] Rtsne_0.17                  yulab.utils_0.2.1          
## [151] spatstat.utils_3.2-0        ggside_0.4.0               
## [153] RcppParallel_5.1.11-1       jquerylib_0.1.4            
## [155] GOSemSim_2.34.0             zeallot_0.2.0              
## [157] spatstat.univar_3.1-4       R.utils_2.13.0             
## [159] lazyeval_0.2.2              shiny_1.11.1               
## [161] htmltools_0.5.8.1           enrichplot_1.28.4          
## [163] GO.db_3.21.0                sctransform_0.4.2          
## [165] rappdirs_0.3.3              glue_1.8.0                 
## [167] spam_2.11-1                 httr2_1.2.1                
## [169] XVector_0.48.0              treeio_1.32.0              
## [171] gridExtra_2.3               R6_2.6.1                   
## [173] labeling_0.4.3              cluster_2.1.8.1            
## [175] pkgload_1.4.1               aplot_0.2.9                
## [177] rstantools_2.5.0            DelayedArray_0.34.1        
## [179] tidyselect_1.2.1            ggforce_0.5.0              
## [181] xml2_1.4.0                  statsExpressions_1.7.1     
## [183] KernSmooth_2.23-26          S7_0.2.1                   
## [185] websocket_1.4.4             htmlwidgets_1.6.4          
## [187] fgsea_1.34.2                biomaRt_2.64.0             
## [189] spatstat.sparse_3.1-0       spatstat.explore_3.5-3     
## [191] remotes_2.5.0               ggnewscale_0.5.2